package com.huashizhaoxi.lionapp.controller;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.huashizhaoxi.lionapp.config.WxPayConfig;
import com.huashizhaoxi.lionapp.entity.FruitOrderChild;
import com.huashizhaoxi.lionapp.entity.FruitOrderMain;
import com.huashizhaoxi.lionapp.entity.Payment;
import com.huashizhaoxi.lionapp.service.FruitOrderService;
import com.huashizhaoxi.lionapp.service.PrepayService;
import com.huashizhaoxi.lionapp.utils.JwtUtils;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import lombok.extern.log4j.Log4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.util.logging.Logger;

@RestController
public class PrepayController {

    Logger log = Logger.getLogger(PrepayController.class.getName());

    @Resource
    private WxPayConfig wxPayConfig;

    @Resource
    private CloseableHttpClient wxPayClient;

    @Resource
    private Verifier verifier;

    @Autowired
    private FruitOrderService fruitOrderService;

    @Autowired
    private PrepayService prepayService;

    @ResponseBody
    @RequestMapping("returnparam")
    public HashMap<String, String> doOrder(HttpServletRequest request, HttpServletResponse response) throws Exception{
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        //得到openid（微信用户唯一的openid）
        String mytoken = request.getHeader("mytoken");
        Map<String,Object> map = JwtUtils.parseJwt(mytoken);
        String openid = (String) map.get("open_id");
        int user_id = (int) map.get("id");
        //得到价钱（自定义）
        String priceStr;
        BigDecimal priceDec = null;
        int type = Integer.parseInt(request.getParameter("type"));
        int fee = 0;
        if (null != request.getParameter("price")) {
            System.out.println(request.getParameter("price"));
            priceStr = request.getParameter("price");
            priceDec = new BigDecimal(priceStr);
            fee = priceDec.multiply(new BigDecimal(100)).intValue();
        }
        //订单标题（自定义）
        String title = request.getParameter("title");
        //时间戳，
        String times = System.currentTimeMillis() + "";

        //订单编号（自定义 这里以时间戳+随机数）
        Random random = new Random();
        String did = times+random.nextInt(1000);

        //调用统一下单API
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
        // 请求body参数
        Gson gson = new Gson();
        HashMap<Object, Object> paramsMap = new HashMap<>();
        paramsMap.put("appid",wxPayConfig.getAppid());//appid
        paramsMap.put("mchid",wxPayConfig.getMchId());//商户号
        paramsMap.put("description",title);//商品描述
        paramsMap.put("out_trade_no",did);//商户订单号
        paramsMap.put("notify_url","https://www.huashizhaoxi.icu:81/pay/notify");//通知地址，可随便写，如果不需要通知的话，不影响支付，但是影响后续修改订单状态

        //订单金额
        HashMap<Object, Object> amountMap = new HashMap<>();
        amountMap.put("total",fee);//金额
        amountMap.put("currency","CNY");//货币类型
        paramsMap.put("amount",amountMap);

        //支付者
        HashMap<Object, Object> playerMap = new HashMap<>();
        playerMap.put("openid",openid);

        paramsMap.put("payer",playerMap);

        //将参数转化未json字符串
        String jsonParamsMap = gson.toJson(paramsMap);
        log.info("请求参数："+jsonParamsMap);

        StringEntity entity = new StringEntity(jsonParamsMap,"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        //完成签名并执行请求
        CloseableHttpResponse resp = wxPayClient.execute(httpPost);

        try {
            int statusCode = resp.getStatusLine().getStatusCode();
            String bodyAsString = EntityUtils.toString(resp.getEntity());
            if (statusCode == 200) { //处理成功
                log.info("成功，返回结果 = " + bodyAsString);
            } else if (statusCode == 204) { //处理成功，无返回Body
                log.info("成功");
            } else {
                System.out.println("小程序下单失败,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
                throw new IOException("request failed");
            }
            //相应结果
            HashMap<String,String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
            log.info("返回结果："+resultMap);


            //获取prepay—id
            String prepayId = resultMap.get("prepay_id");


            //获取到perpayid之后需要对数据进行二次封装，前端调起支付必须存在的参数
            HashMap<String, String> payMap = new HashMap<>();
            payMap.put("appid",wxPayConfig.getAppid());//appid
            long currentTimestamp = System.currentTimeMillis();//时间戳，别管那么多，他就是需要
            payMap.put("timeStamp",currentTimestamp+"");
            String nonceStr = UUID.randomUUID().toString()
                    .replaceAll("-", "")
                    .substring(0, 32);;//随机字符串，别管那么多他就是需要，要咱就给
            payMap.put("nonceStr",nonceStr);
            //apiv3只支持这种加密方式
            payMap.put("signType","RSA");

            payMap.put("package","prepay_id="+prepayId);

            //通过appid，timeStamp，nonceStr，signType，package以及商户密钥进行key=value形式进行拼接加密
            //加密方法我会放在这个代码段段下面
            String aPackage = wxPayConfig.buildMessageTwo("wx6d4ed04668f5e6f7", currentTimestamp, nonceStr, payMap.get("package"));

            //获取对应的签名
            //加密方法我会放在这个代码段段下面
            String paySign = wxPayConfig.sign(wxPayConfig.getPrivateKeyPath(),aPackage.getBytes("utf-8"));

            payMap.put("paySign",paySign);

            /**
             *	在这里你可以加入自己的数据库操作，存储一条订单信息，状态为未支付就行了
             *	在这里你可以加入自己的数据库操作，存储一条订单信息，状态为未支付就行了
             *	在这里你可以加入自己的数据库操作，存储一条订单信息，状态为未支付就行了
             */
            if(type == 1){
                String mainOrder = request.getParameter("fruitOrderMain");
                FruitOrderMain fruitOrderMain = gson.fromJson(mainOrder, FruitOrderMain.class);
                fruitOrderMain.setOrder_id(did);
                fruitOrderMain.setCreate_time(new Timestamp(System.currentTimeMillis()));
                fruitOrderMain.setUser_id(user_id);
                String childList = request.getParameter("fruitOrderChild");
                System.out.println(childList);
                java.lang.reflect.Type listType = new TypeToken<List<FruitOrderChild>>(){}.getType();
                List<FruitOrderChild> fruitOrderChildList = gson.fromJson(childList, listType);
                for(FruitOrderChild fruitOrderChild : fruitOrderChildList){
                    fruitOrderChild.setOrder_id(did);
                }

                fruitOrderService.addFruitMainOrder(fruitOrderMain);
                fruitOrderService.addFruitChildOrder(fruitOrderChildList);
            }


            payMap.put("order_id",did);

            Payment payment = new Payment();
            payment.setOrder_id(did);
            payment.setPrepay_id(prepayId);
            payment.setNonce_str(nonceStr);
            payment.setTimestamp(currentTimestamp);
            payment.setPay_sign(paySign);
            payment.setStatus(1);
            prepayService.addPayment(payment);

            log.info("给前端的玩意："+payMap);//前端会根据这些参数调起支付页面
            //到这里，就已经完成了官网图中的第8步了
            return payMap;

        }finally {
            resp.close();
        }
    }
}
